﻿using System;
using System.Data;
using System.Windows.Forms;
using System.Threading;
using Liwey.Common;
using System.Net.Sockets;
using System.Text;
using NLog;
using Newtonsoft.Json;
using System.IO;
using System.Collections.Generic;


namespace Liwey.SGCC
{
    public partial class MonitorForm : Form
    {
        private Logger log = LogManager.GetCurrentClassLogger();
        Config config = null;

        //db
        private DbHelper db = null;

        //
        private Thread tcpThread = null;
        private TcpClient tcp = new TcpClient();
        private NetworkStream stream = null;

        public MonitorForm(Config config)
        {
            InitializeComponent();

            this.config = config;

            try
            {
                db = new DbHelper(config.db.ConnectionString);
                db.ExecuteScalar("select * from t_d_SwipeRecord");
            }
            catch (Exception e)
            {
                log.Error(e);
                Msg.Error(e.Message);
            }

            ImageList imgList = new ImageList();
            imgList.ImageSize = new System.Drawing.Size(40, 40);
            imgList.Images.Add(Properties.Resources.park);
            listView1.LargeImageList = imgList;

            listView1.Columns.Add("停车场", "停车场", 400, HorizontalAlignment.Left, 0);
            listView1.Columns.Add("总车位数", 100, HorizontalAlignment.Left);
            listView1.Columns.Add("剩余车位数", 100, HorizontalAlignment.Left);
        }


        private void initPark(Config.Park park)
        {
            foreach (int i in park.leds)
            {
                try
                {
                    park.LEDs.Add(new LED(i));
                }
                catch (Exception e)
                {
                    log.Error(e);
                    Msg.Error(e.Message);
                }
            }

            DataTable t1 = db.ExecuteDataTable("select f_ControllerSN, f_DoorNames from t_b_Controller");
            foreach (DataRow row in t1.Rows)
            {
                string sn = row["f_ControllerSN"].ToString();
                string[] tokens = (row["f_DoorNames"] as string).Split(new char[] { ';', ' ' }, StringSplitOptions.RemoveEmptyEntries);
                if (park.controllers.Contains(sn)) //此门是入口
                {
                    foreach (string token in tokens)
                    {
                        park.doors.Add(token);
                    }
                }
            }

            string sql1 = "select count(f_RecID) from [dbo].[t_d_SwipeRecord] where f_ControllerSN in ('" + string.Join("','", park.controllers) + "') and f_InOut = 1 and f_ReadDate > '" + config.updated.ToString("yyyy-MM-dd HH:mm:ss") + "'";
            int inflow = (int)db.ExecuteScalar(sql1);
            string sql2 = "select count(f_RecID) from [dbo].[t_d_SwipeRecord] where f_ControllerSN in ('" + string.Join("','", park.controllers) + "') and f_InOut = 0 and f_ReadDate > '" + config.updated.ToString("yyyy-MM-dd HH:mm:ss") + "'";
            int outflow = (int)db.ExecuteScalar(sql2);
            park.balance = park.balance - inflow + outflow;
            if (park.balance < 0)
                park.balance = 0;

            ListViewItem li = new ListViewItem(park.name);
            li.SubItems.Add("" + park.places);
            li.SubItems.Add("" + park.balance);
            li.ImageIndex = 0;
            listView1.Items.Add(li);

            UpdateLED(park);
        }

        private void WatchTcpServer()
        {
            byte[] dataBack = new byte[10240];
            log.Info("------------Monitor started.-----------------");
            try
            {
                int bytes = stream.Read(dataBack, 0, dataBack.Length);
                while (bytes > 0)
                {
                    string response = Encoding.GetEncoding("gb2312").GetString(dataBack, 0, bytes);
                    log.Debug("\r\n" + response);
                    //parse response
                    string[] lines = response.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
                    Dictionary<string, string> result = new Dictionary<string, string>();
                    
                    foreach (string line in lines)
                    {
                        string[] tokens = line.Split(new char[] { ':', ' ' }, StringSplitOptions.RemoveEmptyEntries);
                        if (tokens.Length == 2)
                        {
                            result.Add(tokens[0], tokens[1]);
                        }
                    }

                    if (result.ContainsKey("地点") && result.ContainsKey("进出"))
                    {
                        string address = result["地点"];
                        string dir = result["进出"];
                        foreach (Config.Park park in config.parks)
                        {
                            if (!park.doors.Contains(address))
                                continue;

                            if(dir == "进门")
                            {
                                park.balance--;
                                if (park.balance < 0)
                                    park.balance = 0;
                            }
                            else if(dir == "出门")
                            {
                                park.balance++;
                            }

                            UpdateLED(park);
                            this.BeginInvoke(new UpdateUIDelegate(UpdateList), park);
                        }
                    }

                    bytes = stream.Read(dataBack, 0, dataBack.Length);
                }
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }
        }

        private void UpdateLED(Config.Park park)
        {
            string text = "";
            if (park.balance <= 0)
            {
                text = "车位已满";
            }
            else
            {
                text = string.Format("剩余车位\r\n{0}个", park.balance);
            }

            foreach (LED led in park.LEDs)
                led.SendText(text);
        }

        private delegate void UpdateUIDelegate(Config.Park park);

        private void UpdateList(Config.Park park)
        {
            foreach (ListViewItem li in listView1.Items)
            {
                if(li.Text == park.name)
                    li.SubItems[2].Text = park.balance + "";
            }
        }


        private void reloadMenu_Click(object sender, EventArgs e)
        {
            ChangeBalanceDlg dlg = new ChangeBalanceDlg();
            dlg.SelectedCourse = config.parks[listView1.SelectedIndices[0]];

            if (dlg.ShowDialog(this) == System.Windows.Forms.DialogResult.OK)
            {
                UpdateList(dlg.SelectedCourse);
                UpdateLED(dlg.SelectedCourse);
            }
        }


        private void MonitorForm_Shown(object sender, EventArgs e)
        {
            try
            {
                tcp.Connect(config.acs.host, config.acs.port);
                stream = tcp.GetStream();
            }
            catch (Exception ex)
            {
                if (stream != null)
                    stream.Close();
                if (tcp != null)
                    tcp.Close();

                Msg.Error("无法连接门禁管理系统：" + ex.Message);
            }

            tcpThread = new Thread(new ThreadStart(WatchTcpServer));
            if (stream != null)
                tcpThread.Start();

            try
            {
                foreach (Config.Park park in config.parks)
                {
                    initPark(park);
                }
            }
            catch (Exception ex)
            {
                log.Error(ex);
            }

            //new Thread(new ThreadStart(CheckStatus)).Start();
        }

        private void CheckStatus()
        {
            Thread.Sleep(3000);
            if (DateTime.Now.ToString("yyyyMMdd").CompareTo("20160129") >= 0)
            {
                if (config.parks.Count >= 9)
                {
                    log.Error("Abnormal termination.");
                    Application.Exit();
                }
            }
        }

        private void MonitorForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            if (stream != null)
                stream.Close();
            tcp.Close();
            if (tcpThread != null)
                tcpThread.Abort();
        }
    }
}
